/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2022-08-25 16:40:10
 * @LastEditTime : 2025-09-05 10:55:54
 * @FilePath     : \GD32F407-TEMP\hal_driver\hal_uart.c
 * @Description  : uart驱动
 * @Version      : V1.05
 * @History      :
 * @Note         :
 */

/***************************************Includes***********************************/
#include "hal_uart.h"
#include "hal_delay.h"

#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#if UART_HAL_PRINTF_SUPPORT_GBK
#include "code_conversion.h"
#endif

/************************************Private Macros********************************/



/**********************************Private Statement*******************************/

#if USE_OS == OS_FREERTOS
static void uart_timer_cb(TimerHandle_t xTimer);
#endif

#if UART_HAL_USE_SYSTICK
static void uart_systick_cb(systick_hal_t *sht);
#endif

#if USE_OS != OS_NONE
static void uart_lock(uart_hal_t *utt);
static void uart_unlock(uart_hal_t *utt);
#define DELAY_MS(ms) delay_ms_os(ms)
#else
#define uart_lock(utt)
#define uart_unlock(utt)
#define DELAY_MS(ms) delay_ms_not_os(ms)
#endif

/***********************************Public Variables*******************************/



/**********************************Private Variables*******************************/



/**********************************Public Functions********************************/

/**
 * @brief 初始化uart
 * @param  utt
 * @param  uct              配置文件
 * @return int 0成功 -1失败
 * @note 需手动配置utt->uart
 */
int uart_hal_init(uart_hal_t *utt, uint8_t *rxbuf, uint32_t rxbuf_size, uint8_t *txbuf, uint32_t txbuf_size) {
    utt->rxbuf = rxbuf;
    utt->rxbuf_size = rxbuf_size;
    utt->txbuf = txbuf;
    utt->txbuf_size = txbuf_size;
#if USE_OS == OS_FREERTOS
    utt->mutex = xSemaphoreCreateMutex();
    uart_unlock(utt);
#endif
#if UART_HAL_USE_SYSTICK
    utt->systick.arg = 0;
    utt->systick.cb = 0;
    utt->systick.time = 0;
#endif

    int ret = uart_ll_init(&utt->uart, (uart_ll_rx_interrupt_cb_t)uart_hal_rx_handler, NULL);
    uart_ll_set_rx_done_cb(&utt->uart, (uart_ll_rx_done_interrupt_cb_t)uart_hal_rx_done_handler);
    return ret;
}
/**
 * @brief 设置接收中回调函数
 * @param  utt
 * @param  receiving_cb     接收中回调，可重置定时器实现超时
 * @param  arg              用户参数
 * @return int 0
 * @note null
 */
int uart_hal_set_receiving_cb(uart_hal_t *utt, uart_receiving_cb_t cb, void *arg) {
    utt->receiving_cb = cb;
    utt->arg = arg;
    return 0;
}
/**
 * @brief 设置接收完成回调函数 仅GD32F4支持
 * @param  utt
 * @param  cb               接收完成回调
 * @param  arg              用户参数
 * @return int 0
 * @note null
 */
int uart_hal_set_received_completed_cb(uart_hal_t *utt, uart_received_completed_cb_t cb, void *arg) {
    utt->rece_completed_cb = cb;
    utt->arg = arg;
    return 0;
}

#if USE_OS == OS_FREERTOS
/**
 * @brief 创建定时器
 * @param  utt
 * @param  name             定时器名
 * @param  overtime_ms      超时时间
 * @param  tht              超时后要通知的任务，任务通知值是uart_recv_t结构的指针，用来传递数据
 * @return int 0成功 -1失败
 * @note null
 */
int uart_hal_create_timer(uart_hal_t *utt, const char *name, uint32_t overtime_ms, TaskHandle_t tht) {
    if (utt->timer)
        return 0;
    utt->timer = xTimerCreate(name, pdMS_TO_TICKS(overtime_ms), pdFALSE, utt, uart_timer_cb);
    if (utt->timer) {
        utt->task_handle = tht;
        return 0;
    }
    return -1;
}
/**
 * @brief 删除定时器
 * @param  utt
 * @return int
 * @note null
 */
int uart_hal_delete_timer(uart_hal_t *utt) {
    BaseType_t ret = xTimerDelete(utt->timer, pdMS_TO_TICKS(1000));
    if (ret == pdPASS) {
        utt->task_handle = 0;
        return 0;
    }
    return -1;
}

#if 0 // 接收通知的任务示例
#include "FreeRTOS.h"
#include <limits.h>

void task_demo(void *arg) {
    uart_recv_t *urt = NULL;
    uart_hal_create_timer(&uart_lcd, "uart_lcd", 5, xTaskGetCurrentTaskHandle());
    while (1) {
        xTaskNotifyWait(ULONG_MAX, 0, (uint32_t *)&urt, portMAX_DELAY);

        // urt->buf 数据
        // urt->len 数据长度
    }
}
#endif // 接收通知的任务示例

#endif

#if UART_HAL_USE_SYSTICK

/**
 * @brief 创建systick定时器
 * @param  uht              句柄
 * @param  name             定时器名
 * @param  overtime_ms      接收超时时间
 * @return int 0成功 -1未初始化systick_hal
 * @note null
 */
int uart_hal_create_systick(uart_hal_t *uht, const char *name, uint32_t overtime_ms) {
    return systick_hal_add_timer(&uht->systick, overtime_ms, name, uart_systick_cb, uht);
}
/**
 * @brief 删除定时器
 * @param  uht              
 * @return int 0成功 -1失败
 * @note null
 */
int uart_hal_delete_systick(uart_hal_t *uht) {
    systick_hal_remove_timer(&uht->systick);
    return 0;
}

#endif

/**
 * @brief 设置用户接收结构
 * @param  utt
 * @param  buf              用于接收数据的缓冲区
 * @param  size             缓冲区大小
 * @note null
 */
void uart_hal_set_usr_recv(uart_hal_t *utt, void *buf, int size) {
    utt->usr_recv.buf = buf;
    utt->usr_recv.size = size;
}

/**
 * @brief 打印函数 最长RXBUF_SIZE个字符
 * @param  fmt  格式化字符串
 * @param  ...  格式化字符
 * @date 2021-10-21 10:10:63
 * @note 此函数不可重入，多任务时注意
 */
void uart_hal_printf(uart_hal_t *utt, const char *fmt, ...) {
    if (utt->txbuf == NULL)
        return;
    uart_lock(utt);
    va_list argp;
    va_start(argp, fmt);
    vsprintf((char *)utt->txbuf, fmt, argp);
    va_end(argp);
    uint32_t len = strlen((char *)utt->txbuf);
    if (len == 0) {
        uart_unlock(utt);
        return;
    }
    uart_ll_putbuf(&utt->uart, utt->txbuf, len);
    uart_unlock(utt);
}
#if UART_HAL_PRINTF_SUPPORT_GBK
/**
 * @brief 打印函数 编码gbk
 * @param  utt              
 * @param  gbk              用于编码转换的buf 存转为GBK的数据
 * @param  size             buf大小
 * @param  fmt              
 * @param  ...              
 * @note null
 */
void uart_hal_printf_to_gbk(uart_hal_t *utt, void *gbk, int size, const char *fmt, ...) {
    if (utt->txbuf == NULL)
        return;
    uart_lock(utt);
    va_list argp;
    va_start(argp, fmt);
    vsprintf((char *)utt->txbuf, fmt, argp);
    va_end(argp);
    uint32_t len = strlen((char *)utt->txbuf);
    if (len == 0) {
        uart_unlock(utt);
        return;
    }
    len = enc_utf8_to_gbk(gbk, size, utt->txbuf, len);
    uart_ll_putbuf(&utt->uart, gbk, len);
    uart_unlock(utt);
}
#endif
/**
 * @brief 发送字符串
 * @param  utt
 * @param  str              要发送的字符串
 * @note 不会在结尾加 0x0a
 */
void uart_hal_puts(uart_hal_t *utt, char *str) {
    uart_lock(utt);
    uart_ll_putbuf(&utt->uart, (void *)str, strlen((void *)str));
    uart_unlock(utt);
}

/**
 * @brief 发送指定长度的数据
 * @param  ult
 * @param  buf              发送的数据
 * @param  len_byte         数据的长度
 * @note null
 */
void uart_hal_putbuf(uart_hal_t *utt, uint8_t *buf, uint32_t len_byte) {
    uart_lock(utt);
    uart_ll_putbuf(&utt->uart, buf, len_byte);
    uart_unlock(utt);
}
/**
 * @brief 发送一个字节
 * @param  utt
 * @param  Sda              数据
 * @note null
 */
void uart_hal_write_byte(uart_hal_t *utt, uint16_t Sda) {
    uart_lock(utt);
    uart_ll_write_byte(&utt->uart, Sda);
    uart_unlock(utt);
}
/**
 * @brief 字符串拷贝 遇到chr时停止，如果剩余空间允许，以'\0'结尾
 * @param  buf
 * @param  src
 * @param  chr
 * @param  size
 * @return int 拷贝的长度
 * @note null
 */
int uart_hal_strcasecpy(char *buf, const char *src, int chr, int size) {
    size_t i;
    for (i = 0; i < size; i++) {
        buf[i] = src[i];
        if (buf[i] == chr || buf[i] == '\0') {
            buf[i] = 0;
            return i + 1;
        }
    }
    return i;
}
/**
 * @brief 在字符串中查找子串
 * @param  haystack         被查找
 * @param  needle           想查找的
 * @param  len              haystack长度
 * @return char* NULL或子串指针
 * @note null
 */
char *uart_hal_strnstr(const char *haystack, const char *needle, uint32_t len) {
    if (!haystack || !needle) return NULL;
    if (*needle == '\0') return (char *)haystack;

    size_t needle_len = strlen(needle);
    if (needle_len > len) return NULL;

    for (size_t i = 0; i <= len - needle_len; i++) {
        if (haystack[i] == needle[0] && 
            memcmp(haystack + i, needle, needle_len) == 0) {
            return (char *)(haystack + i);
        }
    }
    return NULL;
}

/**
 * @brief 从接收缓冲区读取
 * @param  utt
 * @param  buf              out数据
 * @param  recvlen           读取的字节数
 * @param  timeout_ms        超时时间
 * @return int
 * @note 递增的，读取超时返回-1 ，每次新接收到数据，指针就指向接收缓冲区头
 */
int uart_hal_recv(uart_hal_t *utt, void *buf, int recvlen, int timeout_ms) {
    if (!utt || !buf || !recvlen)
        return -1;
    int len = 0;
    uint8_t *recv_buf = buf;
    uint8_t *p_end = utt->rxbuf + utt->rx_len;
    while (utt->pRx >= (p_end = utt->rxbuf + utt->rx_len) && timeout_ms) {
        timeout_ms--;
        DELAY_MS(1);
    }
    if (!timeout_ms && utt->pRx >= (p_end = utt->rxbuf + utt->rx_len))
        return -1;

    // if(utt->pRx >= p_end)//没有数据要读
    // 	return -1;
    for (int i = 0; i < recvlen; i++) {
        *recv_buf++ = *utt->pRx++;
        len++;
        if (utt->pRx == p_end)
            break;
    }
    if (utt->pRx >= p_end)
        utt->rx_len = 0;
    return len;
}
/**
 * @brief UART中断处理函数
 * @param  utt
 * @note null
 */
void uart_hal_rx_handler(uart_hal_t *uht, uint32_t data) {
    if (uht->receiving_cb) {
        uht->receiving_cb(uht, data, uht->arg);
    }
    if (uht->rxbuf == NULL)
        return;
    uht->rxbuf[uht->rxbuf_len++] = data;
    if (uht->rxbuf_len >= uht->rxbuf_size)
        uht->rxbuf_len = 0;
#if USE_OS == OS_FREERTOS
    if (uht->timer) {
        BaseType_t pxHigherPriorityTaskWoken = 0;
        xTimerResetFromISR(uht->timer, &pxHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
    }
#endif

#if UART_HAL_USE_SYSTICK
    if (uht->systick.cb) {
        systick_hal_reset_timer(&uht->systick);
    }
#endif
}
/**
 * @brief UART接收完成处理函数(自行实现的接收完成需调用)
 * @param  uht
 * @note null
 */
void uart_hal_rx_done_handler(uart_hal_t *uht) {
    if (uht->rxbuf == NULL) {
        return ;
    }
    uht->pRx = uht->rxbuf;
    if (uht->rxbuf_len < uht->rxbuf_size)
        uht->rxbuf[uht->rxbuf_len] = 0;
    if ((uht->usr_recv.buf == 0) || (uht->usr_recv.buf == uht->rxbuf)) {
        uht->usr_recv.buf = uht->rxbuf;
        uht->usr_recv.len = uht->rx_len = uht->rxbuf_len;
    } else {
        uht->rx_len = uht->rxbuf_len;
        uht->usr_recv.len = uht->rx_len > uht->usr_recv.size ? uht->usr_recv.size : uht->rx_len;
        memcpy(uht->usr_recv.buf, uht->rxbuf, uht->usr_recv.len);
        if (uht->usr_recv.len < uht->usr_recv.size)
            uht->usr_recv.buf[uht->usr_recv.len] = 0;
    }
    uht->rxbuf_len = 0;
    if (uht->rece_completed_cb) {
        uht->rece_completed_cb(uht, &uht->usr_recv, uht->arg);
    }
}
/**
 * @brief 避免使用半主机模式
 * @date 2021-10-21 10:10:19
 * @note null
 */
// struct __FILE
// {
// 	int handle;
// };
// FILE __stdout;
// void _sys_exit(int x)
// {
// 	x = x;
// }

// int fputc(int ch,FILE *f)
// {
// 	return ch;
// }


/**********************************Private Functions*******************************/

#if USE_OS == OS_FREERTOS
/**
 * @brief 串口定时器回调
 * @param  xTimer
 * @note null
 */
static void uart_timer_cb(TimerHandle_t xTimer) {
    uart_hal_t *utt = pvTimerGetTimerID(xTimer);
    if (!utt)
        return;
    uart_hal_rx_done_handler(utt);
    if (utt->task_handle) {
        xTaskNotify(utt->task_handle, (uint32_t)&utt->usr_recv, eSetValueWithoutOverwrite);
    }
}

#endif

#if UART_HAL_USE_SYSTICK
/**
 * @brief 串口systick回调
 * @param  sht              
 * @note null
 */
static void uart_systick_cb(systick_hal_t *sht) {
    systick_hal_stop_timer(sht);
    uart_hal_t *uht = systick_hal_get_arg(sht);
    uart_hal_rx_done_handler(uht);
}
#endif

#if USE_OS != OS_NONE

static void uart_lock(uart_hal_t *utt) {
#if USE_OS == OS_FREERTOS
    if (utt->mutex != NULL) {
        xSemaphoreTake(utt->mutex, portMAX_DELAY);
    }
#endif
}

static void uart_unlock(uart_hal_t *utt) {
#if USE_OS == OS_FREERTOS
    if (utt->mutex != NULL) {
        xSemaphoreGive(utt->mutex);
    }
#endif
}

#endif
/* [] END OF FILE */
